﻿namespace SsisLdapSource.DirectoryServicesProtocolsExtensions
{
    using System;
    using System.DirectoryServices.Protocols;
    using System.Net;

    public class LdapConnectionFactory 
    {
        private readonly ILdapConnectionPropertiesContainer ldapConnectionPropertiesContainer;

        public LdapConnectionFactory(ILdapConnectionPropertiesContainer ldapConnectionPropertiesContainer)
        {
            if (string.IsNullOrEmpty(ldapConnectionPropertiesContainer.HostOrDomainName))
            {
                throw new ArgumentNullException("ldapConnectionPropertiesContainer", "Host or Domain property can't be null");
            }

            if (ldapConnectionPropertiesContainer.LdapHostPortNumber == 0)
            {
                throw new ArgumentNullException("ldapConnectionPropertiesContainer",  "Port number property must contain a valid int value");
            }
            
            this.ldapConnectionPropertiesContainer = ldapConnectionPropertiesContainer;
        }

        public System.DirectoryServices.Protocols.LdapConnection Create()
        {
            var ldapConnection = new System.DirectoryServices.Protocols.LdapConnection(
                    new LdapDirectoryIdentifier(
                        ldapConnectionPropertiesContainer.HostOrDomainName,
                        ldapConnectionPropertiesContainer.LdapHostPortNumber));

            SetSessionOptions(ldapConnection);
            SetNetworkCredential(ldapConnection);
            ldapConnection.AuthType = ldapConnectionPropertiesContainer.AuthType;
            return ldapConnection;
        }

        private void SetNetworkCredential(DirectoryConnection ldapConnection)
        {
            if (!string.IsNullOrEmpty(ldapConnectionPropertiesContainer.ConnectionAccountName) &&
                !string.IsNullOrEmpty(ldapConnectionPropertiesContainer.ConnectionAccountPassword))
            {
                ldapConnection.Credential = new NetworkCredential(
                    ldapConnectionPropertiesContainer.ConnectionAccountName,
                    ldapConnectionPropertiesContainer.ConnectionAccountPassword);
            }
        }

        private void SetSessionOptions(System.DirectoryServices.Protocols.LdapConnection ldapConnection)
        {
            var sessionOptions = ldapConnection.SessionOptions;
            sessionOptions.ProtocolVersion = 3;
            if (ldapConnectionPropertiesContainer.UseSSLFlag)
            {
                sessionOptions.SecureSocketLayer = true;
            }
        }
    }
}
